#pragma once
#include <functional>
#include <string>

template <class T>
using func_t = std::function<void(T&)>;

template <class T>
class Thread
{
public:
    Thread(const std::string& threadname, func_t<T> func, T data)
        :_tid(0), _threadname(threadname), _isrunning(false), _func(func), _data(data)
    {}

    static void *ThreadRoution(void *args)
    {
        Thread *ts = static_cast<Thread *>(args);
        ts->_func(ts->_data);
    }

    void Start()
    {
        int n = pthread_create(&_tid, nullptr, ThreadRoution, this);
        if(n == 0)
        {
            _isrunning = true;
        }
    }

    void Join()
    {
        if(_isrunning)
        {
            int n = pthread_join(_tid, nullptr);
            if(n == 0)
                _isrunning = false;
        }
    }
    const std::string& GetThreadName()
    {
        return _threadname;
    }
    ~Thread()
    {}
private:
    pthread_t _tid;
    std::string _threadname;
    bool _isrunning;
    func_t<T> _func;
    T _data;
};